package com.easyoffer.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easyoffer.common.util.NetUtils;
import com.easyoffer.constant.RedisConstant;
import com.easyoffer.service.UserService;
import com.easyoffer.common.BaseResponse;
import com.easyoffer.common.ErrorCode;
import com.easyoffer.common.util.ResultUtils;
import com.easyoffer.constant.UserConstant;
import com.easyoffer.exception.BusinessException;
import com.easyoffer.model.dto.user.UserLoginRequest;
import com.easyoffer.model.dto.user.UserRegisterRequest;
import com.easyoffer.model.dto.user.UserUpdateRequest;
import com.easyoffer.model.entity.User;
import com.easyoffer.model.vo.UserVO;
import com.easyoffer.mapper.UserMapper;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RBitSet;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.time.Year;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import java.util.Objects;

/**
* @author 何文斌
* @description 针对表【user(用户)】的数据库操作Service实现
* @createDate 2025-03-15 21:09:28
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService {

    @Autowired
    RedissonClient redissonClient;

    //注册
    @Override
    public BaseResponse<Long> userRegister(UserRegisterRequest registerRequest) {
        String userAccount = registerRequest.getUserAccount();
        String userPassword = registerRequest.getUserPassword();
        String checkPassword = registerRequest.getCheckPassword();
        if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword))
            return ResultUtils.error(ErrorCode.PARAMS_ERROR);
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userAccount",userAccount);
        if (this.count(queryWrapper) > 0)
            return ResultUtils.error(ErrorCode.PARAMS_ERROR,"用户已存在");
        if (userPassword.length() < 8 || checkPassword.length() < 8)
            return ResultUtils.error(ErrorCode.PARAMS_ERROR,"密码长度不能小于8位");
        if (!userPassword.equals(checkPassword))
            return ResultUtils.error(ErrorCode.PARAMS_ERROR,"两次密码不一致");
        User user = new User();
        user.setUserAccount(userAccount);
        user.setUserPassword(MD5.create().digestHex(userPassword +UserConstant.SALT));
        user.setUserRole("user");
        user.setUserAvatar("https://i0.hdslb.com/bfs/face/09427c8707636515e815c1fcb211aedf6b41fad0.jpg@240w_240h_1c_1s_!web-avatar-nav.avif");
        if (this.save(user))
            return ResultUtils.success(user.getId());
        return ResultUtils.error(ErrorCode.PARAMS_ERROR,"注册失败");
    }

    @Override
    public BaseResponse<UserVO> userLogin(UserLoginRequest loginRequest, HttpServletRequest request) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userAccount",loginRequest.getUserAccount());
        User user = this.getBaseMapper().selectOne(queryWrapper);
        if (user == null || !user.getUserPassword().equals(MD5.create().digestHex(loginRequest.getUserPassword() + UserConstant.SALT)))
            return ResultUtils.error(ErrorCode.PARAMS_ERROR,"用户不存在或密码错误");
        if (UserConstant.BAN_ROLE.equals(user.getUserRole()))
            return ResultUtils.error(ErrorCode.PARAMS_ERROR,"用户已被封禁");
        UserVO userVO = new UserVO();
        BeanUtil.copyProperties(user,userVO);
        StpUtil.login(user.getId(), NetUtils.getDeviceType(request.getHeader("user-agent")));
        StpUtil.getSession().set(UserConstant.USER_LOGIN_STATE,userVO);
        return ResultUtils.success(userVO);
    }

    @Override
    public UserVO getLoginUser(HttpServletRequest request) {
        Object obj = StpUtil.getSession().get(UserConstant.USER_LOGIN_STATE);
        if (obj == null)
            return null;
        return (UserVO) obj ;
    }

    @Override
    public BaseResponse<Integer> updateUser(UserUpdateRequest updateRequest, HttpServletRequest request) {
        Long id = updateRequest.getId();
        String userName = updateRequest.getUserName();
        String userAvatar = updateRequest.getUserAvatar();
        String userProfile = updateRequest.getUserProfile();
        String userRole = updateRequest.getUserRole();
        UserVO loginUser = getLoginUser(request);
        if (loginUser == null)
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR);
        //鉴权
        if (!isAdmin(request) && !Objects.equals(loginUser.getId(), id)){
            return ResultUtils.error(ErrorCode.PARAMS_ERROR,"无权限");
        }
        //判空
        if (StringUtils.isAnyBlank(userName,userAvatar,userProfile,userRole)){
            return ResultUtils.success(1);
        }
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        if (StringUtils.isNotBlank(userName))
            updateWrapper.set("userName",userName);
        if (StringUtils.isNotBlank(userAvatar))
            updateWrapper.set("userAvatar",userAvatar);
        if (StringUtils.isNotBlank(userProfile))
            updateWrapper.set("userProfile",userProfile);
        if (StringUtils.isNotBlank(userRole))
            updateWrapper.set("userRole",userRole);
        int updated = this.getBaseMapper().update(updateWrapper);
        if (updated < 0)
            return ResultUtils.error(ErrorCode.OPERATION_ERROR,"更新失败");
        return ResultUtils.success(updated);
    }



    @Override
    public boolean isAdmin(HttpServletRequest request) {
        // 仅管理员可查询
        UserVO loginUser = this.getLoginUser(request);
        if (loginUser == null)
            return false;
        return UserConstant.ADMIN_ROLE.equals(loginUser.getUserRole());
    }

    @Override
    public Boolean userSignIn(Long userId, HttpServletRequest request) {
        if (userId == null) {
            UserVO loginUser = getLoginUser(request);
            if (loginUser == null)
                throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
            userId = loginUser.getId();
        }
        LocalDate now = LocalDate.now();
        int year = now.getYear();
        String signInKey = RedisConstant.getUserSignInKey(year,userId);
        RBitSet signInBitSet = redissonClient.getBitSet(signInKey);
        int dayOfYear = now.getDayOfYear();
        //查询是否已签到
        boolean isSignIn = signInBitSet.get(dayOfYear);
        //如果已签到，则直接返回true,避免重复签到导致以后拓展功能出现问题
        if (isSignIn)
            return true;
        //未签到则设置为已签到，并可以在以后做拓展，例如签到送积分类似活动
        signInBitSet.set(dayOfYear, true);
        isSignIn = signInBitSet.get(dayOfYear);
        return isSignIn;
    }

    @Override
    public List<Integer> getUserSignInRecord(Integer year, Long userId, HttpServletRequest request) {
        UserVO loginUser = getLoginUser(request);
        if (loginUser == null)
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        if (userId == null)
            userId = loginUser.getId();
        if (year == null)
            year = LocalDate.now().getYear();
        String userSignInKey = RedisConstant.getUserSignInKey(year, userId);
        RBitSet signInRBitset = redissonClient.getBitSet(userSignInKey);
        BitSet bitSet = signInRBitset.asBitSet();
        int lengthOfYear = Year.of(year).length();
        int nextSetBit = bitSet.nextSetBit(0);
        List<Integer> result = new ArrayList<>();
        while (nextSetBit >= 0 && nextSetBit <= lengthOfYear){
            result.add(nextSetBit);
            nextSetBit = bitSet.nextSetBit(nextSetBit + 1);
        }
        return result;
    }

}




